<script setup lang="ts">
import { onMounted, reactive, ref, markRaw, shallowRef } from 'vue'
import { ElLoading, ElMessage } from 'element-plus'
import type { DashboardCardVo, DashboardLayoutVo, LayoutCard, LayoutConfig } from '@/type/Dashboard'
import { 
  getAllDashboardCardsApi, 
  getUserDashboardLayoutApi, 
  saveDashboardLayoutApi 
} from '@/api/dashboard-api'
import { getCardComponent } from './cards'
import { useAuthStore } from '@/stores/auth'

const authStore = useAuthStore()

// 从localStorage获取当前用户ID，实际项目中应该从全局状态管理获取
const currentUserId = authStore.userInfo.userId || '001'

// 布局配置
const layoutConfig = reactive<LayoutConfig>({
  cards: []
})

// 当前布局ID
const currentLayoutId = ref<string | null>(null)

// 网格配置
const gridConfig = reactive({
  columns: 12,
  rowHeight: 100,
  margin: 16
})

const isEditMode = ref(false)
const showCardSelector = ref(false)
const isLoading = ref(true)

// 拖拽状态
const dragState = reactive({
  isDragging: false,
  draggingCard: null as LayoutCard | null,
  startX: 0,
  startY: 0,
  startCardX: 0,
  startCardY: 0,
  previewX: 0,
  previewY: 0,
  showPreview: false,
  currentMouseX: 0,
  currentMouseY: 0,
  offsetX: 0,
  offsetY: 0
})

// 调整大小状态
const resizeState = reactive({
  isResizing: false,
  resizingCard: null as LayoutCard | null,
  resizeDirection: '',
  startX: 0,
  startY: 0,
  startWidth: 0,
  startHeight: 0
})

// 所有可用的卡片模板
const cardTemplates = ref<DashboardCardVo[]>([])

// 卡片组件实例映射
const cardComponents = ref<Record<string, any>>({})

onMounted(() => {
  initDashboard()
  setupEventListeners()
})

// 初始化工作台
async function initDashboard() {
  try {
    // 1. 获取所有可用的卡片模板
    const cardsResponse = await getAllDashboardCardsApi()
    if (cardsResponse.data && cardsResponse.data.length > 0) {
      cardTemplates.value = cardsResponse.data
      
      // 预加载所有卡片组件
      await preloadCardComponents(cardsResponse.data)
    }
    
    // 2. 获取用户布局
    const layoutResponse = await getUserDashboardLayoutApi(currentUserId)
    
    if (layoutResponse.data) {
      // 保存布局ID
      currentLayoutId.value = layoutResponse.data.id || null
      
      // 解析布局配置
      const layoutData = layoutResponse.data
      const parsedConfig = JSON.parse(layoutData.layoutConfig)
      if (parsedConfig.cards && parsedConfig.cards.length > 0) {
        layoutConfig.cards = parsedConfig.cards
      }
    }
  } catch (error) {
    console.error('初始化工作台失败:', error)
    ElMessage.error('初始化工作台失败')
  } finally {
    isLoading.value = false
  }
}

// 预加载卡片组件
async function preloadCardComponents(cards: DashboardCardVo[]) {
  for (const card of cards) {
    if (card.componentName) {
      try {
        const component = await getCardComponent(card.componentName)
        if (component) {
          cardComponents.value[card.componentName] = markRaw(component)
        }
      } catch (error) {
        console.error(`Failed to preload card component: ${card.componentName}`, error)
      }
    }
  }
}

function setupEventListeners() {
  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
}

function toggleEditMode() {
  isEditMode.value = !isEditMode.value
}

// 开始拖拽
function startDrag(card: LayoutCard, event: MouseEvent) {
  if (!isEditMode.value) return

  dragState.isDragging = true
  dragState.draggingCard = card
  dragState.startX = event.clientX
  dragState.startY = event.clientY
  dragState.startCardX = card.x
  dragState.startCardY = card.y
  dragState.currentMouseX = event.clientX
  dragState.currentMouseY = event.clientY
  dragState.showPreview = true

  event.preventDefault()
}

// 开始调整大小
function startResize(card: LayoutCard, direction: string, event: MouseEvent) {
  if (!isEditMode.value) return

  resizeState.isResizing = true
  resizeState.resizingCard = card
  resizeState.resizeDirection = 'right-bottom' // 只支持右下角调整
  resizeState.startX = event.clientX
  resizeState.startY = event.clientY
  resizeState.startWidth = card.width
  resizeState.startHeight = card.height

  event.preventDefault()
  event.stopPropagation()
}

// 鼠标移动处理
function handleMouseMove(event: MouseEvent) {
  if (dragState.isDragging && dragState.draggingCard) {
    handleDragMove(event)
  } else if (resizeState.isResizing && resizeState.resizingCard) {
    handleResizeMove(event)
  }
}

// 拖拽移动
function handleDragMove(event: MouseEvent) {
  if (!dragState.isDragging || !dragState.draggingCard) return

  // 更新当前鼠标位置
  dragState.currentMouseX = event.clientX
  dragState.currentMouseY = event.clientY

  // 获取网格容器
  const gridElement = document.querySelector('.dashboard-grid') as HTMLElement
  if (!gridElement) return

  // 获取网格容器的位置和尺寸
  const gridRect = gridElement.getBoundingClientRect()
  const gridCellWidth = (gridRect.width - (gridConfig.columns - 1) * gridConfig.margin) / gridConfig.columns
  const gridCellHeight = gridConfig.rowHeight

  // 计算鼠标在网格中的相对位置
  const relativeX = event.clientX - gridRect.left
  const relativeY = event.clientY - gridRect.top

  // 计算目标网格位置
  const targetGridX = Math.floor((relativeX + gridConfig.margin / 2) / (gridCellWidth + gridConfig.margin))
  const targetGridY = Math.floor((relativeY + gridConfig.margin / 2) / (gridCellHeight + gridConfig.margin))

  // 更新卡片位置
  if (dragState.draggingCard) {
    dragState.draggingCard.x = Math.max(0, targetGridX)
    dragState.draggingCard.y = Math.max(0, targetGridY)
  }

  dragState.showPreview = true
}

// 调整大小移动
function handleResizeMove(event: MouseEvent) {
  if (!resizeState.resizingCard) return

  // 计算鼠标移动的距离
  const deltaX = event.clientX - resizeState.startX
  const deltaY = event.clientY - resizeState.startY

  // 获取网格单元大小
  const gridElement = document.querySelector('.dashboard-grid') as HTMLElement
  if (!gridElement) return

  const gridRect = gridElement.getBoundingClientRect()
  const gridCellWidth = (gridRect.width - (gridConfig.columns - 1) * gridConfig.margin) / gridConfig.columns
  const gridCellHeight = gridConfig.rowHeight

  // 计算网格变化
  const gridDeltaX = Math.round(deltaX / (gridCellWidth + gridConfig.margin))
  const gridDeltaY = Math.round(deltaY / (gridCellHeight + gridConfig.margin))

  if (gridDeltaX !== 0 || gridDeltaY !== 0) {
    let newWidth = resizeState.startWidth
    let newHeight = resizeState.startHeight

    // 右下角调整同时改变宽度和高度
    newWidth = Math.max(1, resizeState.startWidth + gridDeltaX)
    newHeight = Math.max(1, resizeState.startHeight + gridDeltaY)

    // 边界检查
    const maxWidth = gridConfig.columns - resizeState.resizingCard.x
    const maxHeight = 10 // 最大高度限制

    newWidth = Math.min(newWidth, maxWidth)
    newHeight = Math.min(newHeight, maxHeight)

    // 更新卡片尺寸
    if (resizeState.resizingCard) {
      resizeState.resizingCard.width = newWidth
      resizeState.resizingCard.height = newHeight
    }

    // 更新起始位置
    resizeState.startX = event.clientX
    resizeState.startY = event.clientY
    resizeState.startWidth = newWidth
    resizeState.startHeight = newHeight
  }
}

// 鼠标释放
function handleMouseUp() {
  if (dragState.isDragging && dragState.draggingCard) {
    // 应用拖拽位置到实际卡片
    dragState.isDragging = false
    dragState.draggingCard = null
    dragState.showPreview = false
    saveLayout()
  }

  if (resizeState.isResizing) {
    resizeState.isResizing = false
    resizeState.resizingCard = null
    saveLayout()
  }
}

// 更新卡片位置
function updateCardPosition(cardId: string, x: number, y: number) {
  const card = layoutConfig.cards.find(c => c.cardId === cardId)
  if (card) {
    card.x = x
    card.y = y
  }
}

// 添加卡片到布局
function addCardToLayout(cardTemplate: DashboardCardVo) {
  const newLayoutCard: LayoutCard = {
    cardId: cardTemplate.id || '',
    width: 2,
    height: 2,
    x: 0,
    y: 0,
    order: layoutConfig.cards.length + 1,
    config: undefined
  }
  
  layoutConfig.cards.push(newLayoutCard)
  showCardSelector.value = false
}

// 从布局中移除卡片
async function removeCardFromLayout(cardId: string) {
  try {
    const index = layoutConfig.cards.findIndex((c) => c.cardId === cardId)
    if (index !== -1) {
      layoutConfig.cards.splice(index, 1)
    }
    ElMessage.success('卡片已移除')
  } catch (error) {
    console.error('移除卡片失败:', error)
    ElMessage.error('移除卡片失败')
  }
}

// 保存布局
async function saveLayout() {
  const loading = ElLoading.service({
    text: '保存布局中...',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    // 构造布局配置对象
    const layoutConfigObj = {
      cards: layoutConfig.cards
    }
    
    // 构造布局信息对象
    const layoutInfo: DashboardLayoutVo = {
      userId: currentUserId,
      layoutName: '用户布局',
      layoutConfig: JSON.stringify(layoutConfigObj)
    }
    
    // 如果有布局ID，则添加到布局信息中
    if (currentLayoutId.value) {
      layoutInfo.id = currentLayoutId.value
    }
    
    // 保存布局
    await saveDashboardLayoutApi(layoutInfo)
    ElMessage.success('布局已保存')
  } catch (error) {
    console.error('保存布局失败:', error)
    ElMessage.error('保存布局失败')
  } finally {
    loading.close()
  }
}

// 根据卡片ID获取卡片模板信息
function getCardTemplateById(cardId: string) {
  return cardTemplates.value.find(card => card.id === cardId)
}

// 根据卡片ID获取卡片组件
function getCardComponentByName(cardId: string) {
  const cardTemplate = getCardTemplateById(cardId)
  if (cardTemplate && cardTemplate.componentName) {
    return cardComponents.value[cardTemplate.componentName]
  }
  return null
}

// 根据卡片ID获取卡片配置
function getCardConfig(cardId: string) {
  const cardTemplate = getCardTemplateById(cardId)
  return cardTemplate?.config || null
}
</script>

<template>
  <div class="dashboard-container">
    <div class="dashboard-header">
      <h2 class="dashboard-title">仪表盘</h2>
      <div class="dashboard-actions">
        <el-button
          :type="isEditMode ? 'primary' : 'default'"
          @click="toggleEditMode"
          :icon="isEditMode ? 'Check' : 'Edit'"
          circle
        />
        <el-button 
          type="success" 
          @click="saveLayout" 
          icon="DocumentAdd" 
          v-if="isEditMode" 
          circle 
        />
        <el-button 
          type="primary" 
          @click="showCardSelector = true"
          icon="Plus"
          v-if="isEditMode"
          circle
        />
      </div>
    </div>

    <div class="dashboard-content">
      
      <!-- 卡片选择弹出框 -->
      <el-dialog
        v-model="showCardSelector"
        title="选择卡片"
        width="600px"
      >
        <div v-if="cardTemplates.length === 0" class="empty-card-list">
          暂无可用卡片
        </div>
        <div v-else class="card-list">
          <div 
            v-for="card in cardTemplates" 
            :key="card.id"
            class="card-item"
            @click="addCardToLayout(card)"
          >
            <el-icon v-if="card.cardIcon" class="card-icon">
              <component :is="card.cardIcon" />
            </el-icon>
            <span class="card-name">{{ card.cardName }}</span>
          </div>
        </div>
      </el-dialog>
      
      <!-- 加载状态 -->
      <div v-if="isLoading" class="loading-container">
        <el-skeleton :rows="5" animated />
      </div>
      
      <!-- 布局网格 -->
      <div 
        v-else
        class="dashboard-grid"
        :style="{
          '--grid-columns': gridConfig.columns,
          '--grid-row-height': gridConfig.rowHeight + 'px',
          '--grid-margin': gridConfig.margin + 'px'
        }"
      >
        <!-- 拖拽预览 -->
        <div 
          v-if="dragState.isDragging && dragState.showPreview && dragState.draggingCard" 
          class="drag-preview"
          :style="{
            gridColumn: `${dragState.draggingCard.x + 1} / span ${dragState.draggingCard.width || 2}`,
            gridRow: `${dragState.draggingCard.y + 1} / span ${dragState.draggingCard.height || 2}`
          }"
        ></div>
        
        <div
          v-for="card in layoutConfig.cards"
          :key="card.cardId"
          class="dashboard-card"
          :class="{
            'edit-mode': isEditMode,
            'dragging': dragState.isDragging && dragState.draggingCard?.cardId === card.cardId
          }"
          :style="{
            gridColumn: `${card.x + 1} / span ${card.width || 2}`,
            gridRow: `${card.y + 1} / span ${card.height || 2}`
          }"
          @mousedown="startDrag(card, $event)"
        >
          <div class="card-header">
            <div class="card-title-section">
              <el-icon v-if="getCardTemplateById(card.cardId)?.cardIcon" class="card-icon">
                <component :is="getCardTemplateById(card.cardId)?.cardIcon" />
              </el-icon>
              <span class="card-name">{{ getCardTemplateById(card.cardId)?.cardName }}</span>
            </div>
            <div class="card-actions" v-if="isEditMode">
              <el-button
                size="small"
                type="danger"
                text
                @click="removeCardFromLayout(card.cardId)"
                icon="Delete"
              />
            </div>
          </div>

          <div class="card-body">
            <component 
              v-if="getCardComponentByName(card.cardId)" 
              :is="getCardComponentByName(card.cardId)"
              :card-config="getCardConfig(card.cardId)"
            />
            <div v-else class="card-content default-card">
              <div class="card-title">{{ getCardTemplateById(card.cardId)?.cardName }}</div>
              <div class="card-desc">卡片内容区域</div>
            </div>
          </div>
          
          <!-- 调整大小手柄 -->
          <div v-if="isEditMode" class="resize-handles">
            <div
              class="resize-handle resize-handle-corner"
              @mousedown="startResize(card, 'right-bottom', $event)"
            >
              <svg width="14" height="14" viewBox="0 0 14 14" class="resize-icon">
                <path d="M2 12 L12 2 M9 12 L12 9 M12 12 L12 9 L9 12" stroke="currentColor" stroke-width="1.5" fill="none"></path>
              </svg>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.dashboard-container {
  padding: 20px;
  height: 100%;
  background-color: var(--el-bg-color-page);
  display: flex;
  flex-direction: column;
}

.dashboard-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 8px;
  position: sticky;
  top: 0;
  background-color: var(--el-bg-color-page);
  z-index: 100;
  border-bottom: 1px solid var(--el-border-color-light);
  padding-bottom: 16px;
}

.dashboard-title {
  margin: 0;
  color: var(--el-text-color-primary);
  font-size: 24px;
  font-weight: 600;
}

.dashboard-actions {
  display: flex;
  gap: 12px;
}

.dashboard-content {
  flex: 1;
  overflow: hidden;
  margin-top: 24px;
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  padding: 20px;
}

.add-card-button {
  margin-bottom: 20px;
}

.empty-card-list {
  text-align: center;
  padding: 40px;
  color: var(--el-text-color-secondary);
}

.card-list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  max-height: 400px;
  overflow-y: auto;
  padding: 20px;
}

.card-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px;
  border: 1px solid var(--el-border-color-light);
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.card-item:hover {
  border-color: var(--el-color-primary);
  background-color: var(--el-color-primary-light-9);
}

.card-item .card-icon {
  color: var(--el-color-primary);
  font-size: 16px;
}

.card-item .card-name {
  font-size: 14px;
  color: var(--el-text-color-primary);
}



.card-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px;
  border: 1px solid var(--el-border-color-light);
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.card-item:hover {
  border-color: var(--el-color-primary);
  background-color: var(--el-color-primary-light-9);
}

.card-item .card-icon {
  color: var(--el-color-primary);
  font-size: 16px;
}

.card-item .card-name {
  font-size: 14px;
  color: var(--el-text-color-primary);
}

.dashboard-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(var(--grid-columns, 12), 1fr);
  grid-auto-rows: var(--grid-row-height, 100px);
  gap: var(--grid-margin, 16px);
  height: fit-content;
  min-height: 0;
  position: relative;
}

.dashboard-card {
  background: var(--el-bg-color);
  border: 1px solid var(--el-border-color-light);
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  transition: all 0.3s ease;
  position: relative;
  overflow: visible; /* 允许调整大小手柄显示 */
  display: flex;
  flex-direction: column;
}

.dashboard-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.dashboard-card.edit-mode {
  cursor: move;
  border: 2px dashed var(--el-color-primary);
}

.dashboard-card.dragging {
  opacity: 0.5;
  transform: scale(0.95);
  z-index: 1000;
}

.drag-preview {
  background: rgba(64, 158, 255, 0.1);
  border: 2px dashed var(--el-color-primary);
  border-radius: 8px;
  pointer-events: none;
  z-index: 999;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 16px 8px;
  border-bottom: 1px solid var(--el-border-color-lighter);
  cursor: move; /* 显示拖拽手型 */
}

.card-title-section {
  display: flex;
  align-items: center;
  gap: 8px;
}

.card-icon {
  color: var(--el-color-primary);
  font-size: 16px;
}

.card-name {
  font-weight: 600;
  color: var(--el-text-color-primary);
  font-size: 14px;
}

.card-actions {
  display: flex;
  gap: 4px;
}

.card-body {
  padding: 16px;
  flex: 1;
  position: relative;
}

.card-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.resize-handles {
  position: absolute;
  bottom: 0;
  right: 0;
}

.resize-handle-corner {
  position: absolute;
  opacity: 0;
  transition: opacity 0.2s ease;
  z-index: 10;
}

.dashboard-card.edit-mode:hover .resize-handle-corner {
  opacity: 0.9;
}

.resize-handle-corner:hover {
  opacity: 1 !important;
  background: var(--el-color-primary-dark-2);
}

.resize-handle-corner {
  bottom: 2px;
  right: 2px;
  width: 16px;
  height: 16px;
  cursor: nwse-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--el-color-primary);
  border-radius: 2px;
}

.resize-icon {
  color: white;
  stroke-width: 1.5;
}

.default-card .card-title {
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 8px;
}

.default-card .card-desc {
  font-size: 14px;
  color: var(--el-text-color-secondary);
}

@media (max-width: 768px) {
  .dashboard-container {
    padding: 12px;
  }
  
  .dashboard-content {
    flex-direction: column;
  }
  
  .card-selector-panel {
    width: 100%;
  }
  
  .dashboard-header {
    flex-direction: column;
    gap: 16px;
    align-items: flex-start;
  }
  
  .dashboard-actions {
    width: 100%;
    justify-content: flex-start;
  }
}
</style>